package com.cloxtec.scada.service;

import com.alibaba.fastjson.JSONObject;
import com.cloxtec.scada.utils.MongoHelper;
import com.cloxtec.scada.utils.ParamHelper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;
import com.cloxtec.scada.utils.MyJobFactory;
import javax.annotation.Resource;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
public class ScheduledTaskManager {

    @Resource
    private MongoHelper mongoHelper;

    @Resource
    private ParamHelper paramHelper;

    @Resource
    private MqttPubClient mqttPubClient;

    @Resource
    private MyJobFactory myJobFactory;

    private Scheduler scheduler;
    private JSONObject tasks;

    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    private static final String JOB_DEFAULT_GROUP_NAME = "JOB_DEFAULT_GROUP_NAME";
    private static final String TRIGGER_DEFAULT_GROUP_NAME = "TRIGGER_DEFAULT_GROUP_NAME";


    public ScheduledTaskManager() {
        tasks = new JSONObject();
    }

    private List<JSONObject> createMockTasks() {
        List<JSONObject> mockTasks = new ArrayList<>();
        JSONObject task1 = new JSONObject();
        task1.put("id", "task1");
        task1.put("name", "Mock Task 1");

        JSONObject task2 = new JSONObject();
        task2.put("id", "task2");
        task2.put("name", "Mock Task 2");

        mockTasks.add(task1);
        mockTasks.add(task2);
        // 可以添加更多的模拟任务
        return mockTasks;
    }

    private List<JSONObject> createMockReports() {
        List<JSONObject> mockReports = new ArrayList<>();
        JSONObject report1 = new JSONObject();
        report1.put("id", "report1");
        report1.put("name", "Mock report 1");

        JSONObject report2 = new JSONObject();
        report2.put("id", "report2");
        report2.put("name", "Mock report 2");

        mockReports.add(report1);
        mockReports.add(report2);
        // 可以添加更多的模拟报告任务
        return mockReports;
    }

    public void init() {
        //启动所有任务
        // 模拟数据
//        List<JSONObject> taskObjs = new ArrayList<>();
//        taskObjs.add(new JSONObject().put("id", "task1").put("otherField", "value1"));
//        taskObjs.add(new JSONObject().put("id", "task2").put("otherField", "value2"));
//
//        List<JSONObject> reportObjs = new ArrayList<>();
//        reportObjs.add(new JSONObject().put("id", "report1").put("reportType", "type1"));
//        reportObjs.add(new JSONObject().put("id", "report2").put("reportType", "type2"));
        try {
            scheduler = schedulerFactory.getScheduler();
            scheduler.setJobFactory(myJobFactory);
//            List<JSONObject> taskObjs = mongoHelper.find("param_task");

            List<JSONObject> taskObjs = createMockTasks();
            for (JSONObject task : taskObjs) {
                String taskId = task.getString("id");
                tasks.put(taskId, task);
                addTask(taskId);
            }

//            int nSize = taskObjs.size();
//            for (int i = 0; i < nSize; i++) {
//                JSONObject task = taskObjs.get(i);
//                String taskId = task.getString("id");
//                tasks.put(taskId, task);
//                addTask(taskId);
//            }

            List<JSONObject> reportObjs = createMockReports();
            for (JSONObject report : reportObjs) {
                String reportId = report.getString("id");
                tasks.put(reportId, report);
                addReportTask(reportId);
            }
//            taskObjs = mongoHelper.find("param_report");
//            nSize = taskObjs.size();
//            for (int i = 0; i < nSize; i++) {
//                JSONObject task = taskObjs.get(i);
//                String taskId = task.getString("id");
//                tasks.put(taskId, task);
//                addReportTask(taskId);
//            }

            log.info("start jobs finished.");
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("init Scheduler failed");
        }
    }

    /*
     *  增加定时任务
     */
    public int addTask(String taskId) {
        String cronExp = "";
        JSONObject task = paramHelper.getParamById("param_task", taskId);
        if (task != null) {
            cronExp = task.getString("cronExp");
        }

        if (!CronExpression.isValidExpression(cronExp)) {
            log.error("Illegal cron expression format({})", cronExp);
            return 1;
        }

        tasks.put(taskId, task);

        try {
            JobDetail jobDetail = JobBuilder.newJob(TaskTimedCalculate.class)
                    .withIdentity(new JobKey(taskId, JOB_DEFAULT_GROUP_NAME))
                    .usingJobData("taskId", taskId)
                    .build();

            Trigger trigger = TriggerBuilder.newTrigger()
                    .forJob(jobDetail)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                    .withIdentity(new TriggerKey(taskId, TRIGGER_DEFAULT_GROUP_NAME))
                    .build();

            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
            mqttPubClient.broadcastOperationMsg("添加定时任务:" + taskId + " 完成");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            log.error("QuartzManager add job failed");
            delTask(taskId);
            return 2;
        }
        return 0;
    }


    /*
     *  更新定时任务
     */
    public boolean updateTask(String taskId) {
        boolean result = false;
        String cronExp = "";
        JSONObject task = paramHelper.getParamById("param_task", taskId);
        if (task != null) {
            cronExp = task.getString("cronExp");
            tasks.put(taskId, task);
        }
        if (!CronExpression.isValidExpression(cronExp)) {
            log.error("Illegal cron expression format({})", cronExp);
            return result;
        }

        JobKey jobKey = new JobKey(taskId, JOB_DEFAULT_GROUP_NAME);
        TriggerKey triggerKey = new TriggerKey(taskId, TRIGGER_DEFAULT_GROUP_NAME);

        try {
            if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                Trigger newTrigger = TriggerBuilder.newTrigger()
                        .forJob(jobDetail)
                        .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                        .withIdentity(new TriggerKey(taskId, TRIGGER_DEFAULT_GROUP_NAME))
                        .build();
                scheduler.rescheduleJob(triggerKey, newTrigger);
                mqttPubClient.broadcastOperationMsg("定时任务：" + taskId + " 已经更新参数并重新启动");
                result = true;
            } else {
                log.error("update job name:{},group name:{} or trigger name:{},group name:{} not exists..",
                        jobKey.getName(), jobKey.getGroup(), triggerKey.getName(), triggerKey.getGroup());
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
            log.error("update job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
        }
        return result;
    }

    /*
     * 删除定时任务
     */
    public boolean delTask(String taskId) {
        boolean result = false;
        JobKey jobKey = new JobKey(taskId, JOB_DEFAULT_GROUP_NAME);
        try {
            if (scheduler.checkExists(jobKey)) {
                result = scheduler.deleteJob(jobKey);
                tasks.remove(taskId);
                mqttPubClient.broadcastOperationMsg("删除定时任务：" + taskId + " 完成");
            } else {
                log.error("delete job name:{},group name:{} not exists.", jobKey.getName(), jobKey.getGroup());
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
            log.error("delete job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
        }
        return result;
    }

    public JSONObject getTask(String taskId) {
        if (tasks.containsKey(taskId)) {
            return tasks.getJSONObject(taskId);
        } else {
            return null;
        }
    }

    public boolean addReportTask(String taskId) {
        boolean result = false;
        String cronExp = "";
        JSONObject task = paramHelper.getParamById("param_report", taskId);
        if (task != null) {
            cronExp = task.getString("cronExp");
        }

        if (!CronExpression.isValidExpression(cronExp)) {
            log.error("Illegal cron expression format({})", cronExp);
            return result;
        }

        tasks.put(taskId, task);

        try {
            JobDetail jobDetail = JobBuilder.newJob(TaskReportTableData.class)
                    .withIdentity(new JobKey(taskId, JOB_DEFAULT_GROUP_NAME))
                    .usingJobData("taskId", taskId)
                    .build();

            Trigger trigger = TriggerBuilder.newTrigger()
                    .forJob(jobDetail)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                    .withIdentity(new TriggerKey(taskId, TRIGGER_DEFAULT_GROUP_NAME))
                    .build();

            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
            mqttPubClient.broadcastOperationMsg("添加定时任务:" + taskId + " 完成");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            log.error("QuartzManager add job failed");
        }
        return result;
    }

    public boolean delReportTask(String taskId) {
        boolean result = false;
        JobKey jobKey = new JobKey(taskId, JOB_DEFAULT_GROUP_NAME);
        try {
            if (scheduler.checkExists(jobKey)) {
                result = scheduler.deleteJob(jobKey);
                tasks.remove(taskId);
                mqttPubClient.broadcastOperationMsg("删除定时任务：" + taskId + " 完成");
            } else {
                log.error("delete job name:{},group name:{} not exists.", jobKey.getName(), jobKey.getGroup());
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
            log.error("delete job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
        }
        return result;
    }

    public boolean updateReportTask(String taskId) {
        boolean result = false;
        String cronExp = "";
        JSONObject task = paramHelper.getParamById("param_report", taskId);
        if (task != null) {
            cronExp = task.getString("cronExp");
            tasks.put(taskId, task);
        }
        if (!CronExpression.isValidExpression(cronExp)) {
            log.error("Illegal cron expression format({})", cronExp);
            return result;
        }

        JobKey jobKey = new JobKey(taskId, JOB_DEFAULT_GROUP_NAME);
        TriggerKey triggerKey = new TriggerKey(taskId, TRIGGER_DEFAULT_GROUP_NAME);

        try {
            if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                Trigger newTrigger = TriggerBuilder.newTrigger()
                        .forJob(jobDetail)
                        .withSchedule(CronScheduleBuilder.cronSchedule(cronExp))
                        .withIdentity(new TriggerKey(taskId, TRIGGER_DEFAULT_GROUP_NAME))
                        .build();
                scheduler.rescheduleJob(triggerKey, newTrigger);
                mqttPubClient.broadcastOperationMsg("定时任务：" + taskId + " 已经更新参数并重新启动");
                result = true;
            } else {
                log.error("update job name:{},group name:{} or trigger name:{},group name:{} not exists..",
                        jobKey.getName(), jobKey.getGroup(), triggerKey.getName(), triggerKey.getGroup());
            }
        } catch (SchedulerException e) {
            log.error(e.getMessage(), e);
            log.error("update job name:{},group name:{} failed!", jobKey.getName(), jobKey.getGroup());
        }
        return result;
    }


}

